﻿using System;
using System.Collections.Generic;
using ApplicationLibrary;
using ApplicationLibrary.DBManager;
using ApplicationLibrary.SqlConnector;
using Plumber.Accounting.Forms;
using Plumber.Accounting.ModuleData;
using Plumber.Accounting.Reports.DataSet;
using Plumber.Masters.ModuleData;

namespace Plumber.Accounting.Reports
{
    public partial class AccountingSummary : ApplicationLibrary.DBManager.ReportForm
    {
        private enum TypePrint { Admin, Master, All };

        private TypePrint typePrint = TypePrint.All;
        private string Title = string.Empty;
        private DSJournalEntries dsAccountingSummary = null;
        private DRMasterType drMasterType;
        private DRMasterTypeByType dRMasterTypeByType = null;
        private DRMasters drMasters = null;
        private DRTitle drTitle = null;
        private CodeMode codeMode = CodeMode.E_MustExists;
        private string condomType = string.Empty;
        private string adminType = string.Empty;
        private List<string> aggregator = new List<string>();
        private List<string> administ = new List<string>();
        private DRJournalEntry drJournalEntry = null;

        public AccountingSummary()
            : base(Properties.Resources.FN_MonthlySummary)
        {
            InitializeComponent();
        }

        protected override void OnBatchExecute(string reportName)
        {
            LoadData();

            string invoiceStatus = string.Empty;
            if (rdbClosed.Checked)
                invoiceStatus = Properties.Resources.RPT_Payed;
            else if (rdbOpen.Checked)
                invoiceStatus = Properties.Resources.RPT_ToPayed;

            Title = string.Format(Properties.Resources.RPT_AccountingSummary, invoiceStatus);

            if (rdbSelectDate.Checked)
                Title += string.Format(Properties.Resources.RPT_FromDate, ctbFromDate.Text, ctbToDate.Text);
            SetParameterValue("Title", Title);

            //SetParameterValue("HideLogo", rdbLetterHead.Checked || rdbInternal.Checked);
            switch (typePrint)
            {
                case TypePrint.Admin:
                case TypePrint.Master:
                    SetParameterValue("BigHeader", !rdbInternal.Checked);
                    ShowReport(new RPTSummaryAdmin(), dsAccountingSummary);
                    break;

                default:
                    ShowReport(new RPTSummaryAll(), dsAccountingSummary);
                    break;
            }
        }

        protected override void OnDisableControlsForRun()
        {
            rdbAllType_CheckedChanged(this, EventArgs.Empty);
            rdbAllDate_CheckedChanged(this, EventArgs.Empty);
            //cbbMasterType_SelectedIndexChanged(this, EventArgs.Empty);
        }

        protected override void OnAttachData()
        {
            dsAccountingSummary = new DataSet.DSJournalEntries();
            drMasterType = new DRMasterType(DRMasterType.Module.All);
            drMasters = new DRMasters(false);
            drTitle = new DRTitle(false);
            drJournalEntry = new DRJournalEntry(false);
            cbbMasterType.AttachDataReader(new RRMasterTypeNoAdmin());

            dRMasterTypeByType = new DRMasterTypeByType();
            dRMasterTypeByType.Find(MasterTypes.E_Condominium);
            condomType = dRMasterTypeByType.GetValue<string>(PL_MasterType.Code, 0);
            dRMasterTypeByType.Find(MasterTypes.E_Administrator);
            adminType = dRMasterTypeByType.GetValue<string>(PL_MasterType.Code, 0);

            rdrAdmin.AttachCodeType(adminType);
            rdrAdmin.RadarForm = new RadarMasterForm(adminType, RadarMasterForm.Module.Master);

            rdrMasterFrom.RadarForm = new RadarMasterForm(condomType, RadarMasterForm.Module.Master);
            rdrMasterTo.RadarForm = new RadarMasterForm(condomType, RadarMasterForm.Module.Master);

            AddClickableColumn(PL_JournalEntryDetail.JournalNo);

            base.OnAttachData();
        }

        protected override void OnDoubleClickColumn(string column, string value, CrystalDecisions.Windows.Forms.ObjectInfo[] objectInfo)
        {
            if (column == PL_JournalEntryDetail.JournalNo.Name)
            {
                if (drJournalEntry.Find(value))
                {
                    if (drJournalEntry.GetValue<TaxRegisterType>(PL_JournalEntry.TaxRegister) == TaxRegisterType.E_NORegister)
                    {
                        JournalEntries frm = (JournalEntries)GlobalInfo.OpenForm("Plumber.Plumber.Accounting.Forms.JournalEntries", false);
                        frm.FindRecord(new RadarJournalEntryParam(value));
                    }
                    else 
                    {
                        JournalEntriesSalePurchase frm = (JournalEntriesSalePurchase)GlobalInfo.OpenForm("Plumber.Plumber.Accounting.Forms.JournalEntriesSalePurchase", false);
                        frm.FindRecord(new RadarJournalEntryParam(value));
                    }
                }
            }
        }

        protected override void OnBindData()
        {
        }

        private void LoadData()
        {
            dsAccountingSummary.Clear();
            aggregator.Clear();
            typePrint = TypePrint.All;

            QueryBuilder qb = new QueryBuilder(true);
            qb.SetQualified = true;

            qb.Clear();
            qb.AddSelect(PL_JournalEntry.PostingDate);

            qb.AddSelectAll(PL_JournalEntryDetail.Name);
            qb.AddFrom(PL_JournalEntryDetail.Name);
            qb.AddJoin(QueryBuilder.JoinType.INNER, PL_JournalEntry.JournalNo, PL_JournalEntryDetail.JournalNo);

            SqlABParameter pFrom = null, pTo = null, pStatus = null, pMastFrom = null, pMastTo = null;
            if (rdbSelectDate.Checked)
            {
                pFrom = new SqlABParameter("@p1", PL_JournalEntry.PostingDate);
                pTo = new SqlABParameter("@p2", PL_JournalEntry.PostingDate);
                qb.AddBetween(PL_JournalEntry.PostingDate, pFrom, pTo);

                pFrom.Value = ctbFromDate.Today;
                pTo.Value = ctbToDate.Today;
            }

            if (rdbSelType.Checked)
                qb.AddCompare<string>(PL_JournalEntryDetail.Type, cbbMasterType.GetValue<string>());

            if (rdbSelectMaster.Checked && (rdrMasterFrom.Text != "" || rdrMasterTo.Text != ""))
            {
                typePrint = TypePrint.Master;
                pMastFrom = new SqlABParameter("@p4", PL_JournalEntryDetail.Code);
                pMastTo = new SqlABParameter("@p5", PL_JournalEntryDetail.Code);
                pMastFrom.Value = rdrMasterFrom.Text;
                pMastTo.Value = rdrMasterTo.Text;
                qb.AddBetween(PL_JournalEntryDetail.Code, pMastFrom, pMastTo);
            }

            if (cbbMasterType.dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType) == MasterTypes.E_Condominium)
            {
                typePrint = TypePrint.Admin;
                qb.AddSelect(PL_Masters.Administrator);
                qb.AddJoin(QueryBuilder.JoinType.INNER, PL_Masters.Type, PL_JournalEntryDetail.Type);
                qb.AddColumnJoinAnd(PL_Masters.Code, PL_JournalEntryDetail.Code);
                if (rdrAdmin.Text != "")
                    qb.AddCompare<string>(PL_Masters.Administrator, rdrAdmin.Text);
            }

            if (!rdbAllEntries.Checked)
            {
                pStatus = new SqlABParameter("@p3", PL_JournalEntryDetail.Close);
                qb.AddCompare(PL_JournalEntryDetail.Close, pStatus);
                pStatus.Value = rdbClosed.Checked;
            }
            qb.AddOrder(PL_JournalEntry.PostingDate);
            qb.AddOrder(PL_JournalEntry.JournalNo);

            using (SqlABCommand scc = new SqlABCommand(base.providerType, GlobalInfo.SqlConnection))
            {
                scc.CommandText = qb.Query;
                if (rdbSelectDate.Checked)
                {
                    scc.Parameters.Add(pFrom);
                    scc.Parameters.Add(pTo);
                }

                if (!rdbAllEntries.Checked)
                    scc.Parameters.Add(pStatus);

                if (rdbSelectMaster.Checked && (rdrMasterFrom.Text != "" || rdrMasterTo.Text != ""))
                {
                    scc.Parameters.Add(pMastFrom);
                    scc.Parameters.Add(pMastTo);
                }

                SqlABDataReader dr = scc.ExecuteReader();
                string code = string.Empty, type = string.Empty, aggregKey = string.Empty;

                while (dr.Read())
                {
                    switch (typePrint)
                    {
                        case TypePrint.Admin:
                            type = adminType;
                            code = dr.GetValue<string>(PL_Masters.Administrator);
                            break;

                        default:
                            type = dr.GetValue<string>(PL_JournalEntryDetail.Type);
                            code = dr.GetValue<string>(PL_JournalEntryDetail.Code);
                            break;
                    }
                    aggregKey = string.Concat(type, " ", code);
                    if (!aggregator.Contains(aggregKey))
                        AddMaster(type, code);

                    AddRow(dr, aggregKey);
                }
                dr.Close();
            }
        }

        private void LoadPreviousPeriod(string type, string code, DataSet.DSJournalEntries.MasterRow mar)
        {
            QueryBuilder qb = new QueryBuilder(true);
            qb.SetQualified = true;

            qb.Clear();

            qb.AddFunctionAs("SUM({0})", PL_JournalEntryDetail.From);
            qb.AddFunctionAs("SUM({0})", PL_JournalEntryDetail.To);
            qb.AddFrom(PL_JournalEntryDetail.Name);
            qb.AddJoin(QueryBuilder.JoinType.INNER, PL_JournalEntry.JournalNo, PL_JournalEntryDetail.JournalNo);

            SqlABParameter pTo = null, pStatus = null, pMastFrom = null, pMastTo = null;

            pTo = new SqlABParameter("@p1", PL_JournalEntry.PostingDate);
            qb.AddCompare(PL_JournalEntry.PostingDate, pTo, "<");
            pTo.Value = ctbFromDate.Today;

            if (rdbSelType.Checked)
                qb.AddCompare<string>(PL_JournalEntryDetail.Type, cbbMasterType.GetValue<string>());

            if (rdbSelectMaster.Checked && (rdrMasterFrom.Text != "" || rdrMasterTo.Text != ""))
            {
                typePrint = TypePrint.Master;
                pMastFrom = new SqlABParameter("@p4", PL_JournalEntryDetail.Code);
                pMastTo = new SqlABParameter("@p5", PL_JournalEntryDetail.Code);
                pMastFrom.Value = rdrMasterFrom.Text;
                pMastTo.Value = rdrMasterTo.Text;
                qb.AddBetween(PL_JournalEntryDetail.Code, pMastFrom, pMastTo);
            }

            if (cbbMasterType.dRMasterType.GetValue<MasterTypes>(PL_MasterType.MasterType) == MasterTypes.E_Condominium)
            {
                typePrint = TypePrint.Admin;
                qb.AddSelect(PL_Masters.Administrator);
                qb.AddJoin(QueryBuilder.JoinType.INNER, PL_Masters.Type, PL_JournalEntryDetail.Type);
                qb.AddColumnJoinAnd(PL_Masters.Code, PL_JournalEntryDetail.Code);
                if (rdrAdmin.Text != "")
                    qb.AddCompare<string>(PL_Masters.Administrator, rdrAdmin.Text);

                qb.AddGroup(PL_Masters.Administrator);
            }

            if (!rdbAllEntries.Checked)
            {
                pStatus = new SqlABParameter("@p3", PL_JournalEntryDetail.Close);
                qb.AddCompare(PL_JournalEntryDetail.Close, pStatus);
                pStatus.Value = rdbClosed.Checked;
            }

            using (SqlABCommand scc = new SqlABCommand(base.providerType, GlobalInfo.SqlConnection))
            {
                scc.CommandText = qb.Query;
                scc.Parameters.Add(pTo);

                if (!rdbAllEntries.Checked)
                    scc.Parameters.Add(pStatus);

                if (rdbSelectMaster.Checked && (rdrMasterFrom.Text != "" || rdrMasterTo.Text != ""))
                {
                    scc.Parameters.Add(pMastFrom);
                    scc.Parameters.Add(pMastTo);
                }

                SqlABDataReader dr = scc.ExecuteReader();
                double totFrom = 0, totTo = 0;

                while (dr.Read())
                {
                    totFrom += dr.GetValue<double>(PL_JournalEntryDetail.From);
                    totTo   += dr.GetValue<double>(PL_JournalEntryDetail.To);
                }
                dr.Close();

                DataSet.DSJournalEntries.JournalEntryDetailRow jer = dsAccountingSummary.JournalEntryDetail.NewJournalEntryDetailRow();
                jer["Aggregator"] = string.Concat(type, " ", code);
                jer[PL_JournalEntryDetail.JournalNo.Name] = "";
                jer[PL_JournalEntryDetail.Line.Name] = 0;
                jer[PL_JournalEntry.PostingDate.Name] = ctbFromDate.Today.AddDays(-1);

                jer[PL_JournalEntryDetail.Type.Name] = "";
                jer[PL_JournalEntryDetail.DocumentNo.Name] = "";

                jer[PL_JournalEntryDetail.Code.Name] = "";
                jer[PL_JournalEntryDetail.Description.Name] = Properties.Resources.Msg_TotalPreviousPeriod;
                jer[PL_JournalEntryDetail.From.Name] = totFrom > totTo
                                                            ? totFrom - totTo
                                                            : 0;
                jer[PL_JournalEntryDetail.To.Name] = totTo > totFrom
                                                            ? totTo - totFrom
                                                            : 0;
                dsAccountingSummary.JournalEntryDetail.Rows.Add(jer);
            }
        }

        private void AddMaster(string type, string code)
        {
            string key = string.Concat(type, " ", code);
            aggregator.Add(key);
            DataSet.DSJournalEntries.MasterRow mar = dsAccountingSummary.Master.NewMasterRow();
            mar["Aggregator"] = key;

            if (drMasters.Find(type, code))
            {
                string desc = drMasters.GetValue<string>(PL_Masters.Description);
                string address = drMasters.GetValue<string>(PL_Masters.Address);
                string zip = drMasters.GetValue<string>(PL_Masters.ZipCode);
                string city = drMasters.GetValue<string>(PL_Masters.City);
                string county = drMasters.GetValue<string>(PL_Masters.County);
                if (rdbInternal.Checked)
                {
                    desc = string.Concat(desc, " ", address, " ", zip, " ", city, " ", county).Replace("\r\n", " ").Replace("\t", " ");
                }
                else
                {
                    if (drTitle.Find(drMasters.GetValue<string>(PL_Masters.Title)))
                        desc = drTitle.GetValue<string>(PL_Titles.Description) + "\n" + desc;
                    desc = string.Concat(desc, "\n", address, "\n", zip, " ", city, " ", county);
                }
                mar["Description"] = desc;
            }
            else
            {
                drMasterType.Find(type);
                mar["Description"] = drMasterType.GetValue<string>(PL_MasterType.Description);
            }
            if (ckbPrevious.Checked && rdbSelectDate.Checked)
                LoadPreviousPeriod(type, code, mar);

            dsAccountingSummary.Master.Rows.Add(mar);
        }

        private void AddRow(SqlABDataReader dr, string aggregKey)
        {
            DataSet.DSJournalEntries.JournalEntryDetailRow jer = dsAccountingSummary.JournalEntryDetail.NewJournalEntryDetailRow();
            jer["Aggregator"] = aggregKey;
            jer[PL_JournalEntryDetail.JournalNo.Name] = dr.GetValue<string>(PL_JournalEntryDetail.JournalNo);
            jer[PL_JournalEntryDetail.Line.Name] = dr.GetValue<int>(PL_JournalEntryDetail.Line);
            jer[PL_JournalEntry.PostingDate.Name] = dr.GetValue<DateTime>(PL_JournalEntry.PostingDate);

            drMasterType.Find(dr.GetValue<string>(PL_JournalEntryDetail.Type));
            jer[PL_JournalEntryDetail.Type.Name] = drMasterType.GetValue<string>(PL_MasterType.Description);
            jer[PL_JournalEntryDetail.DocumentNo.Name] = dr.GetValue<string>(PL_JournalEntryDetail.DocumentNo);

            jer[PL_JournalEntryDetail.Code.Name] = dr.GetValue<string>(PL_JournalEntryDetail.Code);
            jer[PL_JournalEntryDetail.Description.Name] = dr.GetValue<string>(PL_JournalEntryDetail.Description);
            jer[PL_JournalEntryDetail.From.Name] = dr.GetValue<double>(PL_JournalEntryDetail.From);
            jer[PL_JournalEntryDetail.To.Name] = dr.GetValue<double>(PL_JournalEntryDetail.To);

            dsAccountingSummary.JournalEntryDetail.Rows.Add(jer);
        }

        protected override EmailArgs SendEmail()
        {
            EmailArgs ea = new EmailArgs();
            ea.Subject = Title;
            ea.Attachment = ExportToPdf(Title);
            return ea;
        }

        private void rdbAllType_CheckedChanged(object sender, EventArgs e)
        {
            cbbMasterType.Enabled = rdbSelType.Checked;
            cbbMasterType_SelectedIndexChanged(this, EventArgs.Empty);
            if (rdbAllType.Checked)
                rdbAllMaster.Checked = true;
        }

        private void rdbAllDate_CheckedChanged(object sender, EventArgs e)
        {
            ctbFromDate.Enabled = rdbSelectDate.Checked;
            ctbToDate.Enabled = rdbSelectDate.Checked;
            ckbPrevious.Enabled = rdbSelectDate.Checked && cbbMasterType.GetValue<string>() == condomType;
        }

        private void cbbMasterType_SelectedIndexChanged(object sender, EventArgs e)
        {
            drMasterType.Find(cbbMasterType.GetValue<string>());
            codeMode = drMasterType.GetValue<CodeMode>(PL_MasterType.CodeMode);

            rdbAllMaster.Enabled = rdbSelType.Checked && codeMode != CodeMode.E_IsEmpty;
            rdbSelectMaster.Enabled = rdbSelType.Checked && codeMode != CodeMode.E_IsEmpty;

            rdbAllMaster_CheckedChanged(this, EventArgs.Empty);

            if (codeMode != CodeMode.E_IsEmpty)
            {
                rdrMasterFrom.AttachCodeType(cbbMasterType.GetValue<string>());
                rdrMasterTo.AttachCodeType(cbbMasterType.GetValue<string>());
                //rdrMasterFrom.ReattachCodeType(cbbMasterType.GetValue());
                //rdrMasterTo.ReattachCodeType(cbbMasterType.GetValue());

                rdrMasterFrom.RadarForm = new RadarMasterForm(cbbMasterType.GetValue<string>(), RadarMasterForm.Module.All);
                rdrMasterTo.RadarForm = new RadarMasterForm(cbbMasterType.GetValue<string>(), RadarMasterForm.Module.All);

                rdrAdmin.Enabled = cbbMasterType.GetValue<string>() == condomType && rdbSelType.Checked && rdbAllMaster.Checked;
                ckbPrevious.Enabled = rdbSelectDate.Checked && cbbMasterType.GetValue<string>() == condomType;
            }
        }

        private void rdbAllMaster_CheckedChanged(object sender, EventArgs e)
        {
            rdrMasterFrom.Enabled = rdbSelectMaster.Checked && rdbAllMaster.Enabled && codeMode != CodeMode.E_IsEmpty;
            rdrMasterTo.Enabled = rdbSelectMaster.Checked && rdbAllMaster.Enabled && codeMode != CodeMode.E_IsEmpty;

            rdrAdmin.Enabled = cbbMasterType.GetValue<string>() == condomType && rdbSelType.Checked && rdbAllMaster.Checked;
            ckbPrevious.Enabled = rdbSelectDate.Checked && cbbMasterType.GetValue<string>() == condomType;

            if (rdbAllMaster.Checked || !rdrMasterFrom.Enabled)
                rdrMasterFrom.Text = rdrMasterTo.Text = string.Empty;
        }

        private void rdrMasterFrom_Validated(object sender, EventArgs e)
        {
            if (rdrMasterTo.Text.IsEmpty())
                rdrMasterTo.Text = rdrMasterFrom.Text;
        }

        private void ctbFromDate_Validated(object sender, EventArgs e)
        {
            if (ctbToDate.Today.IsEmpty() || ctbToDate.Today < ctbFromDate.Today)
            {
                int year = ctbFromDate.Today.Year;
                int month = ctbFromDate.Today.Month;
                int mday = DateTime.DaysInMonth(year, month);
                ctbToDate.Today = new DateTime(year, month, mday);
            }
        }

        private void ctbToDate_Validated(object sender, EventArgs e)
        {
            if (ctbToDate.Today < ctbFromDate.Today)
            {
                int year = ctbToDate.Today.Year;
                int month = ctbToDate.Today.Month;
                ctbFromDate.Today = new DateTime(year, month, 1);
            }
        }
    }
}